package Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**静态代理
 *
 * 动态代理：
 * 1.jdk动态代理
 * 2.CGlib动态代理
 *
 * 动态代理：
 * 1.jdk动态代理
 * 2.CGlib动态代理
 * @author ChenweiLin
 * @create 2022-02-19 17:22
 */
public class DynamicProxy {
    public static void main(String[] args) {
        //jdk动态代理测试

        //创建出抽象代理对象
        LawyerProxy lisi = new LawyerProxy(new Zhangsan("李四"));
        LawyerProxy wangwu = new LawyerProxy(new Zhangsan("王五"));
        //jdk动态代理：创建动态代理实例，要求：本体必须实现接口
        //三个参数分别为：1.需要的类加载器 2.被代理类所实现的接口数组 3.抽象出的代理对象
        Speaker s1 = ((Speaker) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), new Class[]{Speaker.class}, lisi));
        Speaker s2 = ((Speaker) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), new Class[]{Speaker.class}, wangwu));
        s1.speak();
        s2.speak();

        //如果是静态代理，那么lisi和wangwu的分别都需要一个自己的代理类
        //通过jdk动态代理，就只需要抽象出自己的代理对象
        //Zhangsan这个代理对象实现了Speaker这个接口，我们需要将这个接口告诉给Proxy.newProxyInstance
        //因此jdk动态代理有个缺点，若一个类没有实现接口，就无法被代理
        //接下来引入CGlib动态代理

        //CGlib动态代理：是jdk代理的补充，不需要本体实现接口
        //CGlib的调用过程：
        LawyerInterceptor interceptor = new LawyerInterceptor(new Zhangsan("林晨炜"));
        //第一个参数是被代理的类，第二个参数是 实例化的抽象代理类
        Speaker speaker = (Speaker) Enhancer.create(Zhangsan.class, interceptor);
        speaker.speak();


    }


}


//Jdk动态代理
//将律师的行为抽象出来
class LawyerProxy implements InvocationHandler{

    private Object obj = new Object();//准备一个obj对象

    public LawyerProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("speak")){//如果注入方法的名称是speak
            System.out.println("引用法律条文");
            method.invoke(obj, args);//通过反射将代理的method 注入到 obj中， args为method方法的参数
            System.out.println("打人是不对的");
        }

        return null;
    }
}


//CGlib动态代理

class LawyerInterceptor implements MethodInterceptor{

    private Object obj = new Object();//准备一个obj对象

    public LawyerInterceptor(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("我是GCLib");
        System.out.println("引用法律条文");
        method.invoke(obj, args);//通过反射将代理的method 注入到 obj中， args为method方法的参数
        System.out.println("打人是不对的");
        return null;
    }
}
